<?php

namespace app\index\service;

use app\admin\dao\AxbRecordDao;
use app\common\model\Member;
use app\common\model\Trade;
use app\index\traits\PaymentProxyTrait;
use app\index\traits\PaymentTrait;
use app\index\traits\SourceBroadcastTrait;
use ary\Ary;
use ShidianUtil\Concurrent\Synchronizer;
use ShidianUtil\Utils\ConvertUtil;
use think\facade\Log;

/**
 * AXB通话结果处理
 * Class AxbResultCallbackService
 * @package app\index\service
 */
class AxbResultCallbackService
{
    use PaymentTrait;
    use PaymentProxyTrait;
    use SourceBroadcastTrait;

    private AxbRecordDao $axbRecordDao;

    public function __construct(AxbRecordDao $axbRecordDao)
    {

        $this->axbRecordDao = $axbRecordDao;
    }

    /**
     * AXB通话结束回调（实际处理）
     * @param array $params
     * @return void
     */
    public function handle(array $params): void
    {

        // 去重
        try {

            $source = null;
            $sourceId = $params['sourceId'] ?? '';
            $response = $this->getAry()->getSourceDetail(['source_id' => $sourceId]);
            if ($response->isSuccess()) {
                $decodeContents = $response->getDecodeContents();
                $source = $decodeContents['data'] ?? null;
            }

            $params['source'] = $source;

            $record = $this->axbRecordDao->insertActive($params);

            $record = $record->toArray();

            unset($record['source']);
        } catch (\Exception $exception) {
            // 插入失败可能是通话记录ID重复了
            return;
        }

        // 这里一定是通过成功结束，而不是没接通等情况


        if (!isset($params['sourceId']) || !isset($params['memberId'])) {
            Log::error('AXB回调处理参数错误，参数：' . ConvertUtil::jsonEncode($params));
            return;
        }

        try {

            // 处理获客卡
            $this->handleCard($params, $record, $source);

        } catch (\Exception $exception) {

            Log::error('AXB回调处理获客卡失败：params = ' . ConvertUtil::jsonEncode($params) . ' record = ' . ConvertUtil::jsonEncode($record) . ' source = ' . ConvertUtil::jsonEncode($source));
        }

        // 创建通信币订单并支付
        $this->handleCoin($params, $record, $source);

        // 添加案源购买播报
        $member = Member::where('id', $params['memberId'])->find();
        $lawyerName = '';
        if ($member) {
            $lawyerName = $member->showName;
        }
        $this->addBroadcast($params['memberId'], $lawyerName, $source['type_name'] ?? '');

    }

    // 处理获客卡
    private function handleCard(array $params, $record, $source)
    {

        $sourceId = $params['sourceId'];
        $memberId = $params['memberId'];
        $num = $params['num'];
        $price = $params['price'];

        $trade = $this->queryTrade($sourceId, $memberId);

        if (!$trade) {

            //

            // 这里同步处理，防止重复创建订单
            $signature = Trade::class . TRADE_SOURCE . $memberId;
            $this->getSynchronizer()->synchronized($signature, function () use (&$trade, $sourceId, $memberId, $num, $price, $record, $source) {

                $trade = $this->queryTrade($sourceId, $memberId);

                if (!$trade) {
                    // 创建订单

                    $trade = $this->getTradeSourceService()->append($memberId, $sourceId, $num, $price, $record, $source);
                }

            });


            if ($trade && $trade->payStatus == Trade::UNPAID) {
                // 支付订单


                // 如果可以代付，并且限额足够
                $proxy = false;
                $member = Member::where('id', $memberId)->find();
                if ($member && is_id($member->companyId)) {
                    $proxy = $this->checkProxyQuota($member->id, $member->companyId, $member->userPersonnelId, PAYMENT_CARD);
                }

                // 判断代付
                if ($proxy) {

                    // 代付
                    $this->getProxyPayment($trade->payMethod)->proxyCompanyPay($trade, $member->companyId, $member->userPersonnelId, true);
                } else {

                    // 立即进行支付，允许欠费
                    $this->getPayment($trade->payMethod)->pay($trade, true);
                }

            }
        }
    }

    // 处理通信币
    private function handleCoin(array $params, $record, $source)
    {
        $sourceId = $params['sourceId'];
        $memberId = $params['memberId'];
        $talkTime = $params['talkTime'];

        $trade = $this->getTradeAxbCommunicationService()->append($memberId, $sourceId, $talkTime, $record, $source);

        // 如果可以代付，并且限额足够
        $proxy = false;
        $member = Member::where('id', $memberId)->find();
        if ($member && is_id($member->companyId)) {
            $proxy = $this->checkProxyQuota($member->id, $member->companyId, $member->userPersonnelId, PAYMENT_COIN);
        }

        // 判断代付
        if ($proxy) {

            // 代付
            $this->getProxyPayment($trade->payMethod)->proxyCompanyPay($trade, $member->companyId, $member->userPersonnelId, true);
        } else {

            // 立即进行支付，允许欠费
            $this->getPayment($trade->payMethod)->pay($trade, true);
        }
    }

    /**
     * 查询用户的已付款案源订单
     * @param $sourceId
     * @param $memberId
     * @return Trade|null
     */
    private function queryTrade($sourceId, $memberId): ?Trade
    {
        return Trade::where('sourceId', $sourceId)
            ->where('memberId', $memberId)
            ->where('tradeType', TRADE_SOURCE)
            ->where('payStatus', Trade::PAID)
            ->whereIn('refundStatus', [Trade::NOTREFUND, Trade::REFUNDING, Trade::REFUND_FAILED])
            ->field(true)
            ->find();
    }

    private function getTradeSourceService(): TradeSourceService
    {
        return app(TradeSourceService::class);
    }

    private function getTradeAxbCommunicationService(): TradeAxbCommunicationService
    {
        return app(TradeAxbCommunicationService::class);
    }

    private function getSynchronizer(): Synchronizer
    {
        return app(Synchronizer::class);
    }

    private function getAry(): Ary
    {
        return app(Ary::class);
    }
}
